import { defineComponent, cloneVNode, ComponentPublicInstance, computed, getCurrentInstance, nextTick, onMounted, onUpdated, PropType, provide, ref, VNode, watchEffect, Transition } from 'vue'
import { getEL, getSlot } from '../_util/props-util';
import Trigger from '../trigger'
import { OptionListProps } from './OptionList';

export default defineComponent({
  name: 'SelectTrigger',
  props: {
    prefixCls: String,
    popup: Object as PropType<VNode>,
    popupStyle: String,
    visible: Boolean,
    disabled: Boolean,
    filterable: Boolean,
  },
  setup(props) {
    const { prefixCls } = props

    const scrollRef = ref<ComponentPublicInstance<OptionListProps>>()
    const popupRef = ref()
    const alignRef = ref<{forceAlign: Function}>()

    const targetRef = ref<ComponentPublicInstance>()

    provide('popupRef', popupRef)
    provide('alignRef', alignRef)

    const getSelectedEl = () => (scrollRef.value?.$el as HTMLElement).querySelector('.selected') as HTMLElement

    const offset = ref(0)
    const popupAlign = computed(() => props.filterable
      ? { offset: [0, 0] }
      : {
        points: ['tl', 'tl'],
        offset: [0, offset.value],
        overflow: { adjustX: 0, adjustY: 0 },
        targetOffset: [0, 0],
      }
    )
    function PopupTransition(_, { slots }) {
      return <Transition appear onEnter={onPopupEnter} v-slots={slots} />
    }
    function onPopupEnter() {
      const scrollEl = scrollRef.value?.$el as HTMLElement
      if (!scrollEl) return
      
      const selectedEl = getSelectedEl() ?? scrollEl.querySelector(`.${prefixCls}-option`)
      if (!selectedEl) return

      const targetEl = getEL(targetRef.value)
      if (!targetEl) return

      offset.value = 0
      alignRef.value.forceAlign()
      offset.value = targetEl.getBoundingClientRect().top - selectedEl.getBoundingClientRect().top

      requestAnimationFrame(() => {
        const scrollY = selectedEl.offsetTop
        scrollEl.scroll(scrollEl.scrollLeft, scrollY)
      })
    }

    return vm => {
      const listboxPreCls = `${prefixCls}-listbox`
      const popup = cloneVNode(props.popup, { ref: scrollRef }, true)
      
      return (
        <Trigger
          popup={popup}
          popupClass={listboxPreCls}
          popupStyle={props.popupStyle}
          popupVisible={props.visible}
          popupPlacement={props.filterable ? 'bottomLeft' : undefined}
          popupTransition={PopupTransition}
          popupTransitionName={listboxPreCls}
          popupAlign={popupAlign}
        >
          {cloneVNode(getSlot(vm)[0], { ref: targetRef })}
        </Trigger>
      )
    }
  }
})